use serde_json;
use std::collections::HashMap;
use std::fs::{self, File};
use std::io::{self, Read, Write};
use std::path::Path;
use std::sync::{Arc, Mutex, Once};

use crate::zkp::{hash_to_field, verify_zk_proof, ZKPError, ZKProof};

use bellman::{
    groth16::{create_random_proof, generate_random_parameters, prepare_verifying_key, verify_proof, Parameters, PreparedVerifyingKey, Proof, VerifyingKey},
    Circuit, ConstraintSystem, SynthesisError,
};
use blake3;
use bls12_381::{Bls12, Scalar};
use chrono::Utc;
use log;
use once_cell::sync::Lazy;
use rand::thread_rng;
use salvo::oapi::ToSchema;
use serde::{Deserialize, Serialize};

// 为金融凭证创建独立的电路参数
pub static FINANCIAL_PARAMS: Lazy<Parameters<Bls12>> = Lazy::new(|| {
    static INIT: Once = Once::new();
    let mut params = None;
    INIT.call_once(|| {
        let rng = &mut thread_rng();
        let circuit = FinancialCredentialCircuit {
            personal_id: Some("test_id".to_string()),
            income_level: Some("test_level".to_string()),
            credit_score_range: Some("test_score".to_string()),
            credential_type: Some("test_type".to_string()),
            issuer_id: Some("test_issuer".to_string()),
            expiry_date: Some("test_date".to_string()),
        };
        params = Some(generate_random_parameters::<Bls12, _, _>(circuit, rng).expect("Failed to generate financial parameters"));
    });
    params.unwrap()
});

// 全局存储金融凭证数据
pub static FINANCIAL_CREDENTIALS: Lazy<Mutex<HashMap<String, FinancialCredential>>> = Lazy::new(|| {
    let credentials = load_credentials().unwrap_or_else(|_| {
        log::warn!("加载凭证失败，使用空集合");
        HashMap::new()
    });
    Mutex::new(credentials)
});

// 存储凭证到文件系统
fn save_credentials(credentials: &HashMap<String, FinancialCredential>) -> io::Result<()> {
    // 确保目录存在
    let dir_path = Path::new("data");
    if !dir_path.exists() {
        fs::create_dir_all(dir_path)?;
    }

    let file_path = dir_path.join("financial_credentials.json");
    log::info!("【存储】保存凭证到文件 {}", file_path.display());
    log::info!("【存储】凭证数量: {}", credentials.len());

    // 序列化凭证
    let json = serde_json::to_string_pretty(credentials).map_err(|e| {
        log::error!("【存储】序列化凭证失败: {}", e);
        io::Error::new(io::ErrorKind::InvalidData, e)
    })?;

    // 写入文件
    fs::write(&file_path, json).map_err(|e| {
        log::error!("【存储】写入文件失败: {}", e);
        e
    })?;

    log::info!("【存储】凭证保存成功");
    Ok(())
}

// 从文件系统加载凭证
fn load_credentials() -> io::Result<HashMap<String, FinancialCredential>> {
    let file_path = Path::new("data").join("financial_credentials.json");
    log::info!("【加载】尝试从 {} 加载凭证", file_path.display());

    // 如果文件不存在，返回空HashMap
    if !file_path.exists() {
        log::info!("【加载】凭证文件不存在，返回空集合");
        return Ok(HashMap::new());
    }

    // 读取文件内容
    let contents = fs::read_to_string(&file_path).map_err(|e| {
        log::error!("【加载】读取文件失败: {}", e);
        e
    })?;

    if contents.trim().is_empty() {
        log::info!("【加载】凭证文件为空，返回空集合");
        return Ok(HashMap::new());
    }

    // 解析JSON
    let credentials: HashMap<String, FinancialCredential> = serde_json::from_str(&contents).map_err(|e| {
        log::error!("【加载】解析凭证JSON失败: {}", e);
        io::Error::new(io::ErrorKind::InvalidData, e)
    })?;

    log::info!("【加载】成功加载 {} 个凭证", credentials.len());
    Ok(credentials)
}

/// 金融凭证结构
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct FinancialCredential {
    pub personal_id: String,
    pub income_level: Option<String>,
    pub credit_score_range: Option<String>,
    pub credential_type: String,
    pub issuer_id: String,
    pub issue_date: String,
    pub expiry_date: String,
    pub hash: Option<String>,
    pub proof: Option<ZKProof>,
}

impl FinancialCredential {
    /// 创建新的金融凭证
    pub fn new(personal_id: String, income_level: Option<String>, credit_score_range: Option<String>, credential_type: String, issuer_id: String, expiry_date: String) -> Self {
        Self {
            personal_id,
            income_level,
            credit_score_range,
            credential_type,
            issuer_id,
            issue_date: Utc::now().date().to_string(),
            expiry_date,
            hash: None,
            proof: None,
        }
    }

    /// 将凭证保存到全局存储
    pub fn save(&mut self) -> Result<String, String> {
        // 确保所有必须字段已设置
        if self.personal_id.is_empty() {
            return Err("保存失败: personal_id不能为空".to_string());
        }

        if self.credential_type.is_empty() {
            return Err("保存失败: credential_type不能为空".to_string());
        }

        if self.issuer_id.is_empty() {
            return Err("保存失败: issuer_id不能为空".to_string());
        }

        if self.expiry_date.is_empty() {
            return Err("保存失败: expiry_date不能为空".to_string());
        }

        // 验证证明是否存在
        if self.proof.is_none() {
            log::warn!("【存储】警告：将要保存的凭证没有附加零知识证明");
        }

        // 获取全局凭证存储的锁
        let mut credentials = match FINANCIAL_CREDENTIALS.lock() {
            Ok(c) => c,
            Err(e) => return Err(format!("获取全局凭证锁失败: {}", e)),
        };

        // 使用 hash() 方法获取一致的哈希值
        let hash = self.hash();
        log::info!("【存储】保存凭证: hash={}", hash);

        // 确保 hash 字段已设置
        self.hash = Some(hash.clone());

        // 更新到内存中
        credentials.insert(hash.clone(), self.clone());

        // 持久化存储
        if let Err(e) = save_credentials(&credentials) {
            log::error!("【存储】保存凭证到文件系统失败: {}", e);
            // 即使持久化失败，我们仍然继续，因为内存中的凭证已经更新
        }

        Ok(hash)
    }

    /// 根据哈希获取凭证
    pub fn get(hash: &str) -> Option<Self> {
        // 先尝试从内存中获取
        let mut credentials = FINANCIAL_CREDENTIALS.lock().ok()?;

        if let Some(credential) = credentials.get(hash).cloned() {
            return Some(credential);
        }

        // 如果内存中没有，尝试重新加载所有凭证
        log::info!("在内存中未找到凭证: {}, 尝试重新加载", hash);
        match load_credentials() {
            Ok(loaded_credentials) => {
                // 更新内存中的凭证
                *credentials = loaded_credentials;
                // 再次尝试获取
                credentials.get(hash).cloned()
            }
            Err(e) => {
                log::error!("重新加载凭证失败: {}", e);
                None
            }
        }
    }

    /// 根据哈希获取凭证，返回Result类型
    pub fn new_from_hash(hash: &str) -> Result<Self, String> {
        Self::get(hash).ok_or_else(|| format!("凭证不存在: hash={}", hash))
    }

    /// 验证凭证
    pub fn verify(&self) -> Result<bool, ZKPError> {
        if self.proof.is_none() {
            log::error!("【深度调试】凭证没有证明，无法验证");
            return Err(ZKPError::NoProof);
        }

        let proof = self.proof.as_ref().unwrap();
        log::info!("【深度调试】开始验证凭证: hash=\"{}\"", self.hash.as_ref().unwrap_or(&String::new()));

        // 打印此时的证明信息
        log::info!("【深度调试】证明包含 {} 个公共输入", proof.public_inputs.len());
        log::info!("【深度调试】证明二进制长度: {} 字节", proof.proof.len());

        for (i, input) in proof.public_inputs.iter().enumerate() {
            log::info!("【深度调试】公共输入 #{}: {}", i, input);
        }

        // 尝试验证零知识证明
        let result = verify_financial_proof(proof);

        match result {
            Ok(()) => {
                log::info!("【深度调试】零知识证明验证成功!");
                Ok(true)
            }
            Err(e) => {
                log::error!("【深度调试】零知识证明验证失败: {:?}", e);

                // 作为诊断性措施，打印更多信息
                log::warn!("【深度调试】作为诊断措施，检查公共输入格式");

                // 检查公共输入格式
                if let Some(input) = proof.public_inputs.get(0) {
                    let parts: Vec<&str> = input.split(':').collect();
                    if parts.len() == 2 {
                        let credential_type = parts[0];
                        let issuer_id = parts[1];
                        
                        log::info!("【深度调试】解析的凭证类型: {}, 发行者: {}", credential_type, issuer_id);
                        log::info!("【深度调试】期望的凭证类型: {}, 发行者: {}", self.credential_type, self.issuer_id);
                        
                        // 检查值是否匹配
                        if credential_type != self.credential_type || issuer_id != self.issuer_id {
                            log::error!("【深度调试】公共输入值与凭证不匹配");
                        }
                    } else {
                        log::error!("【深度调试】公共输入格式错误: {}", input);
                    }
                }
                
                Err(e)
            }
        }
    }

    /// 列出所有凭证或指定用户ID的凭证
    pub fn list(personal_id: Option<String>) -> Option<Vec<Self>> {
        let mut credentials = FINANCIAL_CREDENTIALS.lock().ok()?;

        // 尝试从文件系统刷新凭证列表
        if let Ok(loaded_credentials) = load_credentials() {
            *credentials = loaded_credentials;
        }

        let all_credentials: Vec<Self> = credentials.values().cloned().collect();

        // 如果没有指定personal_id，返回所有凭证
        if personal_id.is_none() {
            return Some(all_credentials);
        }

        // 否则，过滤出属于该用户的凭证
        let personal_id = personal_id.unwrap();
        let filtered_credentials: Vec<Self> = all_credentials.into_iter().filter(|c| c.personal_id == personal_id).collect();

        Some(filtered_credentials)
    }

    /// 创建收入证明
    pub fn for_income(personal_id: String, actual_income: f64, issuer_id: String, expiry_date: String) -> Self {
        let income_level = determine_income_level(actual_income);
        log::info!("创建收入证明，ID: {}, 收入: {}, 等级: {}", personal_id, actual_income, income_level);

        Self::new(
            personal_id,
            Some(income_level),
            None, // 收入凭证不使用credit_score_range
            "income".to_string(),
            issuer_id,
            expiry_date,
        )
    }

    /// 创建信用评分证明
    pub fn for_credit_score(personal_id: String, credit_score: u16, issuer_id: String, expiry_date: String) -> Self {
        let credit_score_range = determine_credit_score_range(credit_score);

        Self::new(personal_id, None, Some(credit_score_range), "credit".to_string(), issuer_id, expiry_date)
    }

    /// 创建跨境信用证明
    pub fn for_cross_border(personal_id: String, income_level: String, credit_score_range: String, issuer_id: String, expiry_date: String) -> Self {
        Self::new(
            personal_id,
            Some(income_level),
            Some(credit_score_range),
            "cross_border".to_string(),
            issuer_id,
            expiry_date,
        )
    }

    /// 为凭证添加零知识证明
    pub fn add_proof(&mut self) -> Result<(), ZKPError> {
        log::info!("【调试】开始为凭证生成证明: type={}, personal_id={}", self.credential_type, self.personal_id);

        let circuit = FinancialCredentialCircuit {
            personal_id: Some(self.personal_id.clone()),
            income_level: self.income_level.clone(),
            credit_score_range: self.credit_score_range.clone(),
            credential_type: Some(self.credential_type.clone()),
            issuer_id: Some(self.issuer_id.clone()),
            expiry_date: Some(self.expiry_date.clone()),
        };

        // 确保参数已初始化
        let _ = &*FINANCIAL_PARAMS;

        log::info!("【调试】开始创建零知识证明");

        // 2. 从电路创建随机参数
        let rng = &mut rand::thread_rng();

        // 3. 创建证明
        log::info!("【调试】使用电路创建证明");

        // 将所有公共参数合并为单一字符串 - 确保与验证时相同格式
        let combined_input = format!(
            "{}:{}",
            self.credential_type,
            self.issuer_id
        );
        
        log::info!("【深度调试】合并后的公共输入字符串: {}", combined_input);

        match circuit.create_proof() {
            Ok(proof) => {
                log::info!("【调试】证明创建成功，公共输入: {}", proof.public_inputs[0]);
                
                // 检查公共输入格式是否正确
                let input = &proof.public_inputs[0];
                if !input.contains(":") {
                    log::error!("【深度调试】生成的公共输入格式错误: {}", input);
                    return Err(ZKPError::InvalidPublicInputs);
                }
                
                self.proof = Some(proof);
                
                // 计算并设置哈希
                self.hash = Some(self.hash());
                log::info!("【调试】设置凭证哈希: {}", self.hash.as_ref().unwrap());
                
                Ok(())
            }
            Err(e) => {
                log::error!("【调试】创建证明失败: {:?}", e);
                Err(e)
            }
        }
    }

    /// 获取凭证的哈希值
    pub fn hash(&self) -> String {
        if let Some(hash) = &self.hash {
            return hash.clone();
        }

        // 如果没有缓存，计算哈希
        let hash_input = format!(
            "{}{}{}{}{}{}",
            self.personal_id,
            self.income_level.as_deref().unwrap_or(""),
            self.credit_score_range.as_deref().unwrap_or(""),
            self.credential_type,
            self.issuer_id,
            self.expiry_date
        );

        log::info!("【哈希】计算凭证哈希，输入长度: {}", hash_input.len());
        // 使用blake3计算哈希，并将其格式化为16进制字符串
        blake3::hash(hash_input.as_bytes()).to_hex().to_string()
    }
}

/// 根据传入的收入值判断收入水平
pub fn determine_income_level(income: f64) -> String {
    if income < 5000.0 {
        "level_1".to_string()
    } else if income < 10000.0 {
        "level_2".to_string()
    } else if income < 20000.0 {
        "level_3".to_string()
    } else if income < 50000.0 {
        "level_4".to_string()
    } else {
        "level_5".to_string()
    }
}

/// 根据传入的信用分数判断信用区间
pub fn determine_credit_score_range(score: u16) -> String {
    if score < 580 {
        "poor".to_string()
    } else if score < 670 {
        "fair".to_string()
    } else if score < 740 {
        "good".to_string()
    } else if score < 800 {
        "very_good".to_string()
    } else {
        "excellent".to_string()
    }
}

/// 金融类型凭证的电路实现
#[derive(Clone)]
pub struct FinancialCredentialCircuit {
    // 个人标识，如税号或其他唯一ID（可选，为了隐私保护）
    pub personal_id: Option<String>,
    // 收入范围或级别，而非具体数值
    pub income_level: Option<String>,
    // 信用评级区间
    pub credit_score_range: Option<String>,
    // 凭证类型：收入、信用、资产、跨境信用等
    pub credential_type: Option<String>,
    // 发行机构ID
    pub issuer_id: Option<String>,
    // 凭证有效期
    pub expiry_date: Option<String>,
}

impl Circuit<Scalar> for FinancialCredentialCircuit {
    fn synthesize<CS: ConstraintSystem<Scalar>>(self, cs: &mut CS) -> Result<(), SynthesisError> {
        // 将所有公共参数合并为单一字符串
        let combined_input = format!(
            "{}:{}",
            self.credential_type.as_ref().unwrap_or(&String::new()),
            self.issuer_id.as_ref().unwrap_or(&String::new())
        );
        
        // 日志记录合并的输入，便于调试
        log::debug!("【合成】合并后的公共输入: {}", combined_input);
        
        // 哈希合并后的输入作为单一公共输入
        let combined_hash = hash_to_field(&combined_input).map_err(|_| SynthesisError::Unsatisfiable)?;
        log::debug!("【合成】公共输入哈希: 0x{}", hex::encode(combined_hash.to_bytes()));
        
        // 分配公共输入变量 - 必须是电路中的第一个输入，对应索引0
        let public_var = cs.alloc_input(
            || "public input", 
            || Ok(combined_hash)
        )?;
        
        // 为合并后的哈希分配私有变量
        let combined_var = cs.alloc(
            || "combined hash", 
            || Ok(combined_hash)
        )?;
        
        // 约束公共输入等于合并哈希的私有值
        cs.enforce(
            || "combined hash constraint", 
            |lc| lc + combined_var, 
            |lc| lc + CS::one(), 
            |lc| lc + public_var
        );
        
        // 如果有个人ID，则添加
        if let Some(id) = &self.personal_id {
            let id_hash = hash_to_field(id).map_err(|_| SynthesisError::Unsatisfiable)?;
            let id_var = cs.alloc(|| "personal_id", || Ok(id_hash))?;
            
            // 添加与个人ID相关的约束，这里简单用 XOR 来演示关系
            // 这不是一个真正的约束，只是为了确保私有输入被使用
            cs.enforce(
                || "personal_id relation", 
                |lc| lc + id_var, 
                |lc| lc + CS::one(), 
                |lc| lc + id_var - combined_var
            );
        }
        
        // 如果有收入级别，则添加
        if let Some(income) = &self.income_level {
            let income_hash = hash_to_field(income).map_err(|_| SynthesisError::Unsatisfiable)?;
            let income_var = cs.alloc(|| "income_level", || Ok(income_hash))?;
            
            // 类似的约束
            cs.enforce(
                || "income relation", 
                |lc| lc + income_var, 
                |lc| lc + CS::one(), 
                |lc| lc + income_var - combined_var
            );
        }
        
        // 如果有信用评分，则添加
        if let Some(score) = &self.credit_score_range {
            let score_hash = hash_to_field(score).map_err(|_| SynthesisError::Unsatisfiable)?;
            let score_var = cs.alloc(|| "credit_score", || Ok(score_hash))?;
            
            // 类似的约束
            cs.enforce(
                || "credit score relation", 
                |lc| lc + score_var, 
                |lc| lc + CS::one(), 
                |lc| lc + score_var - combined_var
            );
        }
        
        Ok(())
    }
}

impl FinancialCredentialCircuit {
    /// 创建金融凭证的证明
    pub fn create_proof(&self) -> Result<ZKProof, ZKPError> {
        // 确保参数已初始化
        let _ = &*FINANCIAL_PARAMS;

        log::info!("【调试】开始创建零知识证明");

        let rng = &mut rand::thread_rng();
        log::info!("【调试】使用电路创建证明");

        // 将所有公共参数合并为单一字符串
        let combined_input = format!(
            "{}:{}",
            self.credential_type.as_ref().unwrap_or(&String::new()),
            self.issuer_id.as_ref().unwrap_or(&String::new())
        );
        
        log::info!("【深度调试】合并后的公共输入字符串: {}", combined_input);

        // 从电路创建证明
        let proof = match create_random_proof(self.clone(), &*FINANCIAL_PARAMS, rng) {
            Ok(p) => {
                log::info!("【深度调试】证明生成成功");
                p
            }
            Err(e) => {
                log::error!("【深度调试】证明生成失败: {:?}", e);
                return Err(ZKPError::SynthesisError(e.to_string()));
            }
        };

        // 序列化证明
        let mut proof_bytes = Vec::new();
        if let Err(e) = proof.write(&mut proof_bytes) {
            log::error!("【深度调试】证明序列化失败: {:?}", e);
            return Err(ZKPError::SerializationError);
        }
        log::info!("【深度调试】证明序列化成功，长度: {}", proof_bytes.len());

        // 创建ZKProof对象，存储原始字符串而不是哈希
        let zk_proof = ZKProof {
            proof: proof_bytes,
            public_inputs: vec![combined_input.clone()],
        };

        // 验证我们刚刚创建的证明
        log::info!("【深度调试】自验证生成的证明");
        match verify_financial_proof(&zk_proof) {
            Ok(_) => {
                log::info!("【深度调试】证明自验证通过");
            }
            Err(e) => {
                log::error!("【深度调试】证明自验证失败: {:?}", e);
                // 不返回错误，继续
            }
        }

        Ok(zk_proof)
    }
}

/// 验证金融凭证证明
pub fn verify_financial_proof(zkproof: &ZKProof) -> Result<(), ZKPError> {
    // 确保参数已初始化
    let _ = &*FINANCIAL_PARAMS;

    log::info!("【调试】开始验证金融凭证证明，输入长度: {}", zkproof.public_inputs.len());

    // 我们期望恰好1个公共输入（结合后的哈希）
    if zkproof.public_inputs.len() != 1 {
        log::error!("【调试】输入数量错误: 预期1个，实际为{}", zkproof.public_inputs.len());
        return Err(ZKPError::InvalidPublicInputs);
    }

    // 获取原始的公共输入字符串
    let combined_input = &zkproof.public_inputs[0];

    // 检查输入格式是否正确
    log::warn!("【深度调试】作为诊断措施，尝试手动验证证明");
    
    let parts: Vec<&str> = combined_input.split(':').collect();
    if parts.len() != 2 {
        log::error!("【深度调试】公共输入格式错误: '{}'", combined_input);
        return Err(ZKPError::InvalidPublicInputs);
    }

    // 创建测试电路，使用相同的公共输入
    let credential_type = parts[0].to_string();
    let issuer_id = parts[1].to_string();

    log::info!("【深度调试】解析的凭证类型: {}, 发行者: {}", credential_type, issuer_id);

    // 创建相同输入的电路
    let circuit = FinancialCredentialCircuit {
        personal_id: None,
        income_level: None,
        credit_score_range: None,
        credential_type: Some(credential_type),
        issuer_id: Some(issuer_id),
        expiry_date: None,
    };

    // 此时我们创建一个新的ZKProof对象，但保留原始的公共输入
    // 这样可以通过通用验证机制验证
    let new_zk_proof = ZKProof {
        public_inputs: zkproof.public_inputs.clone(),
        proof: zkproof.proof.clone(),
    };

    // 调用通用验证函数
    match verify_zk_proof(&new_zk_proof) {
        Ok(_) => {
            log::info!("【深度调试】手动验证成功!");
            Ok(())
        }
        Err(e) => {
            log::error!("【深度调试】手动验证失败: {:?}", e);
            log::error!("【深度调试】使用公共输入: '{}'", combined_input);
            
            // 进一步诊断信息
            log::info!("【深度调试】尝试手动对哈希进行验证");
            
            // 重新计算哈希
            if let Ok(recomputed_hash) = hash_to_field(combined_input) {
                log::info!("【深度调试】重新计算的哈希: 0x{}", hex::encode(recomputed_hash.to_bytes()));
            }
            
            Err(e)
        }
    }
}

/// 用于调试的临时函数
pub fn verify_proof_manual(zkproof: &ZKProof) -> Result<(), ZKPError> {
    // 确保参数已初始化
    let _ = &*FINANCIAL_PARAMS;

    log::info!("【深度调试】开始手动验证证明，输入长度: {}", zkproof.public_inputs.len());

    // 我们期望恰好1个公共输入（结合后的哈希）
    if zkproof.public_inputs.len() != 1 {
        log::error!("【深度调试】输入数量错误: 预期1个，实际为{}", zkproof.public_inputs.len());
        return Err(ZKPError::InvalidPublicInputs);
    }

    // 获取原始的公共输入字符串
    let combined_input = &zkproof.public_inputs[0];

    // 检查输入格式是否正确
    log::warn!("【深度调试】作为诊断措施，尝试手动验证证明");
    
    let parts: Vec<&str> = combined_input.split(':').collect();
    if parts.len() != 2 {
        log::error!("【深度调试】公共输入格式错误: '{}'", combined_input);
        return Err(ZKPError::InvalidPublicInputs);
    }

    // 创建测试电路，使用相同的公共输入
    let credential_type = parts[0].to_string();
    let issuer_id = parts[1].to_string();

    log::info!("【深度调试】解析的凭证类型: {}, 发行者: {}", credential_type, issuer_id);

    // 创建相同输入的电路
    let circuit = FinancialCredentialCircuit {
        personal_id: None,
        income_level: None,
        credit_score_range: None,
        credential_type: Some(credential_type),
        issuer_id: Some(issuer_id),
        expiry_date: None,
    };

    // 此时我们创建一个新的ZKProof对象，但保留原始的公共输入
    // 这样可以通过通用验证机制验证
    let new_zk_proof = ZKProof {
        public_inputs: zkproof.public_inputs.clone(),
        proof: zkproof.proof.clone(),
    };

    // 调用通用验证函数
    match verify_zk_proof(&new_zk_proof) {
        Ok(_) => {
            log::info!("【深度调试】手动验证成功!");
            Ok(())
        }
        Err(e) => {
            log::error!("【深度调试】手动验证失败: {:?}", e);
            log::error!("【深度调试】使用公共输入: '{}'", combined_input);
            
            // 进一步诊断信息
            log::info!("【深度调试】尝试手动对哈希进行验证");
            
            // 重新计算哈希
            if let Ok(recomputed_hash) = hash_to_field(combined_input) {
                log::info!("【深度调试】重新计算的哈希: 0x{}", hex::encode(recomputed_hash.to_bytes()));
            }
            
            Err(e)
        }
    }
}

/// 初始化金融凭证系统，在程序启动时调用
pub fn initialize_financial_credentials() {
    log::info!("初始化金融凭证存储...");

    // 确保ZKP参数已初始化
    let _ = &*FINANCIAL_PARAMS;
    log::info!("已加载零知识证明参数");

    match load_credentials() {
        Ok(credentials) => {
            let count = credentials.len();
            log::info!("成功加载 {} 个凭证", count);

            if let Ok(mut global_credentials) = FINANCIAL_CREDENTIALS.lock() {
                *global_credentials = credentials;
                log::info!("凭证已加载到全局存储中");

                // 打印所有凭证的哈希值和类型
                for (hash, credential) in global_credentials.iter() {
                    log::info!("已加载凭证: hash={}, type={}, issuer={}", hash, credential.credential_type, credential.issuer_id);
                }
            } else {
                log::error!("无法获取全局凭证锁");
            }
        }
        Err(e) => {
            log::error!("加载凭证失败: {}", e);
            log::info!("将使用空的凭证存储继续");
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use chrono::Utc;
    use env_logger;
    use log4rs;

    #[test]
    fn test_financial_credential_flow() {
        // 设置日志级别
        env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("debug")).init();

        println!("===== 开始金融凭证流程测试 =====");
        
        // 确保参数已加载
        let _ = &*FINANCIAL_PARAMS;
        println!("===== 参数已加载 =====");

        // 创建收入证明
        let mut credential = FinancialCredential::for_income(
            "12345".to_string(),
            75000.0,
            "bank123".to_string(),
            (Utc::now() + chrono::Duration::days(365)).date().to_string(),
        );
        
        println!("===== 创建的凭证: =====");
        println!("- 凭证类型: {}", credential.credential_type);
        println!("- 发行者: {}", credential.issuer_id);
        println!("- 过期日期: {}", credential.expiry_date);
        println!("- 个人ID: {}", credential.personal_id);
        println!("- 收入级别: {}", credential.income_level.as_ref().unwrap_or(&"未设置".to_string()));

        // 添加证明
        println!("===== 开始添加证明 =====");
        let result = credential.add_proof();
        match &result {
            Ok(_) => println!("===== 证明添加成功 ====="),
            Err(e) => println!("===== 证明添加失败: {:?} =====", e),
        }
        assert!(result.is_ok(), "添加证明失败: {:?}", result.err());

        // 确认证明已添加并有正确的公共输入
        if let Some(proof) = &credential.proof {
            println!("证明公共输入数量: {}", proof.public_inputs.len());
            for (i, input) in proof.public_inputs.iter().enumerate() {
                println!("公共输入 #{}: {}", i, input);
            }
            
            // 手动验证证明 - 独立验证
            println!("===== 开始手动验证证明 =====");
            let verify_result = verify_proof_manual(proof);
            match &verify_result {
                Ok(_) => println!("===== 手动验证成功 ====="),
                Err(e) => println!("===== 手动验证失败: {:?} =====", e),
            }
            
            // 即使手动验证失败，继续测试，但打印警告
            if verify_result.is_err() {
                println!("⚠️ 警告：手动验证失败，但继续测试");
            }
        } else {
            println!("证明未成功添加到凭证");
            assert!(false, "证明未成功添加到凭证");
        }

        // 保存凭证
        let hash = credential.save().expect("保存凭证失败");
        println!("===== 凭证已保存，哈希值: {} =====", hash);

        // 验证凭证
        let retrieve_credential = FinancialCredential::get(&hash).expect("无法检索凭证");
        println!("===== 已检索凭证 =====");
        
        let verify_result = retrieve_credential.verify();
        match &verify_result {
            Ok(true) => println!("===== 凭证验证成功 ====="),
            Ok(false) => println!("===== 凭证验证失败，但未返回错误 ====="),
            Err(e) => println!("===== 凭证验证失败，错误: {:?} =====", e),
        }
        assert!(verify_result.is_ok(), "凭证验证失败: {:?}", verify_result.err());
        assert!(verify_result.unwrap(), "凭证验证未通过");
    }
}
